-- @Author: baidwwy
-- @Date:   2018-04-10 22:51:52
-- @Last Modified by:   baidwwy
-- @Last Modified time: 2018-08-26 16:14:02

local GUI基类     = require("gge界面/基类")
local GUI按钮类   = require("gge界面/按钮类")
local GUI列表类   = require("gge界面/列表类")
local GUI多列表类 = require("gge界面/多列表类")
local GUI滑块类   = require("gge界面/滑块类")
local GUI进度类   = require("gge界面/进度类")
local GUI富文本类 = require("gge界面/富文本类")
local GUI树形类   = require("gge界面/树形类")
local GUI自适应类 = require("gge界面/自适应类")
local GUI网格类   = require("gge界面/网格类")
local GUI输入类   = require("gge界面/输入类")
local GUI多输入类 = require("gge界面/多输入类")
local GUI标签类   = require("gge界面/标签类")
local function _控件排序(a,b) return a._层次 < b._层次 end
local function _添加控件(self,对象,名称)
    对象._层次 = #self._子控件
    self[名称] = 对象
    table.insert(self._子控件, 对象)
end

--======================================================================--
local GUI创建基类 = class()
local GUI控件类   = class(GUI基类,GUI创建基类)
--======================================================================--
    function GUI创建基类:初始化()
        self._子控件 = {}
    end
    function GUI创建基类:取子控件(名称)
        return self[名称]
    end
    function GUI创建基类:释放控件(名称)
        local 控件 = self[名称]
        if 控件 then
            for i,v in ipairs(self._子控件) do
                if v == 控件 then
                    table.remove(self._子控件, i)
                    break
                end
            end
            self[名称] = nil
        end
    end
    function GUI创建基类:子控件消息(...)
        for i,v in ipairs(self._子控件) do
            v:发送消息(...)
        end
    end
    function GUI创建基类:取子控件列表()
        return self._子控件
    end
    function GUI创建基类:遍历子控件()
        return next,self._子控件
    end
    function GUI创建基类:取底层控件()
        return self._子控件[1]
    end
    function GUI创建基类:取顶层控件()
        return self._子控件[#self._子控件]
    end
    function GUI创建基类:排序()
        table.sort(self._子控件,_控件排序)
    end

    function GUI创建基类:创建按钮(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此按钮已存在，不能重复创建.")end
        local 对象         = GUI按钮类.创建(名称,x,y,宽度,高度,self)--基类
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建控件(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此控件已存在，不能重复创建.")end
        local 对象         = GUI控件类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建输入(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此输入已存在，不能重复创建.")end
        local 对象         = GUI输入类.创建(名称,x or 0,y or 0,宽度 or 200,高度 or 20,self)
        _添加控件(self,对象,名称)
        GUI输入类.列表[对象] = 对象
        return 对象
    end
    function GUI创建基类:创建多输入(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此输入已存在，不能重复创建.")end
        local 对象         = GUI多输入类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        GUI输入类.列表[对象] = 对象
        return 对象
    end
    function GUI创建基类:创建富文本(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此丰富文本已存在，不能重复创建.")end
        local 对象         = GUI富文本类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建滑块(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此滑块已存在，不能重复创建.")end
        local 对象         = GUI滑块类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end

    function GUI创建基类:创建列表(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此列表已存在，不能重复创建.")end
        local 对象         = GUI列表类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建多列表(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此多列表已存在，不能重复创建.")end
        local 对象         = GUI多列表类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建进度(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此进度已存在，不能重复创建.")end
        local 对象         = GUI进度类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建树形(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此树形已存在，不能重复创建.")end
        local 对象         = GUI树形类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建自适应(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此自适应已存在，不能重复创建.")end
        local 对象         = GUI自适应类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建网格(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此网格已存在，不能重复创建.")end
        local 对象         = GUI网格类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    function GUI创建基类:创建标签(名称,x,y,宽度,高度)
        if self[名称] then error(名称..":此标签已存在，不能重复创建.")end
        local 对象         = GUI标签类.创建(名称,x,y,宽度,高度,self)
        _添加控件(self,对象,名称)
        return 对象
    end
    --======================================================================--
    function GUI创建基类:创建复选按钮(名称,x,y,宽度,高度)
        local 对象 = self:创建按钮(名称,x,y,宽度,高度)
        对象._类型 = '复选按钮'
        return 对象
    end
    function GUI创建基类:创建单选按钮(名称,x,y,宽度,高度)
        local 对象 = self:创建按钮(名称,x,y,宽度,高度)
        对象._类型 = '单选按钮'
        return 对象
    end
    function GUI创建基类:创建横形滑块(名称,x,y,宽度,高度)
        local 对象 = self:创建滑块(名称,x,y,宽度,高度)
        对象._类型 = '横形滑块'
        return 对象
    end
    GUI创建基类.创建竖形滑块 = GUI创建基类.创建滑块
    function GUI创建基类:创建竖形进度(名称,x,y,宽度,高度)
        local 对象 = self:创建进度(名称,x,y,宽度,高度)
        对象._类型 = '竖形进度'
        return 对象
    end
    function GUI创建基类:创建竖形标签(名称,x,y,宽度,高度)
        local 对象 = self:创建标签(名称,x,y,宽度,高度)
        对象._类型 = '竖形标签'
        return 对象
    end
    GUI创建基类.创建横形进度 = GUI创建基类.创建进度
    function GUI创建基类:创建窗口(名称,x,y,宽度,高度)
        local 对象 = self:创建控件(名称,x,y,宽度,高度)
        对象._可视 = false
        对象._父窗口 = 对象
        对象._类型 = '窗口'
        return 对象
    end

--======================================================================--

function GUI控件类:初始化(名称,x,y)
    self._精灵 = require("gge精灵类")()
    self._右键关闭 = false
end
function GUI控件类:_更新(dt,x,y)
    --if self.更新 then  self:更新(dt,x,y)end
    if self:是否加载() and self:是否可视() then
        if self._鼠标按下 and 引擎.鼠标弹起(KEY.LBUTTON) then
            self._鼠标按下 = false
        end
        for i,v in ipairs(self._子控件) do
            if v:是否加载() and v:是否可视() then
                if v._更新 then v:_更新(dt,x,y) end
                if v.更新 then v:更新(dt,x,y) end
            end
        end
    end
end
function GUI控件类:_显示(x,y)
    if self:是否加载() and self:是否可视() then
        if self._编辑 and self:_编辑显示(x,y) then
            return
        end
        if self.底显示 then self:底显示(self._x,self._y,x,y)end
        self._精灵:显示(self._x,self._y)
        if self.显示   then self:显示(self._x,self._y,x,y)  end
        for k,v in ipairs(self._子控件) do
            if v:是否加载() and v:是否可视() then
                if v._显示  then v:_显示(x,y) end
            end
        end
        if self.顶显示 then self:顶显示(self._x,self._y,x,y)end
        if self._调试 then self._包围盒:显示() end
    end
end
function GUI控件类:置纹理(v)
    if checkggetype(v)=='texture' or not v then
        self._精灵:置纹理(v)
    elseif checkggetype(v)=='sprite' then
        self._精灵 = v
    elseif type(v)=='table' and v.取像素 and v.检查点 and v.取包围盒 and v.显示 then
        self._精灵 = v
    else
        error('置纹理对象错误')
        return
    end
    self._包围盒 = self._精灵:取包围盒()
    return self
end
function GUI控件类:置右键关闭(v)
    self._右键关闭 = v
    return self
end
function GUI控件类:检查像素(x,y)
    return bit.rshift(self._精灵:取像素(x,y), 24) ~= 0
end
function GUI控件类:取精灵()
    return self._精灵
end
function GUI控件类:复制()

end

function GUI控件类:加载(sub)
    self[GUI基类]:加载()
    if (self:取类型() == '窗口' or sub) then--初始化所有子控件
        for k,v in ipairs(self._子控件) do
            if not v:是否加载() then
                v:加载(sub)
            end
        end
    end
end
function GUI控件类:置可视(v,sub)
    if not v and self._禁止关闭 then
        return
    end
    self[GUI基类]:置可视(v,sub)
    if self:是否可视() then
        self:_消息事件('鼠标移动',{引擎.取鼠标坐标()})
        if self._类型 == '窗口' then--打开置顶
            self._层次 = os.clock() + 1000
            self:取父控件():排序()
        end
    end
    return self
end
function GUI控件类:置禁止关闭(v)
    self._禁止关闭 = v
end
function GUI控件类:_消息事件(类型,参数)
    local x,y = unpack(参数)
    if self:发送消息("消息事件",类型,参数) then
        return true
    end
    if self:是否加载() or 类型 == '坐标事件' then
        --父先收消息,以便拦截
        if self:是否可视() and 类型 == '左键按下' then--点击子控件,让窗口置顶
            local 控件 = self:取所在窗口()
            if 控件 and 控件:检查像素(x,y) then
                控件._层次 = os.clock() + 1000
                控件:取父控件():排序()--窗口的控件容器
            end
        end
        if (self:是否可视() or 类型 == '可视事件')  and self:发送消息(类型,x,y,参数) then
            return true--用户消息事件 拦截
        end
        if 类型 == '坐标事件' then--置坐标
            if x~=self._x or y ~= self._y then
                self._fx,self._fy = x,y
                self._x,self._y = self._px+x,self._py+y
                self._包围盒:置坐标(x,y)
                参数={self._x,self._y}
            end
        end
        for i=#self._子控件,1,-1 do--发给子控件
            local v = self._子控件[i]
            if v:是否可视() and v._类型 == '窗口' and self:是否键盘消息(类型) then
                v:_消息事件(类型,参数)--不能拦截,界面层还要,待优化
                break
            elseif 类型 == '坐标事件' then
                v:_消息事件(类型,参数)
            elseif (v:是否可视() or 类型 == '可视事件') and v:_消息事件(类型,参数) then
                return true--子控件 拦截
            end
        end
        if self:是否可视() or 类型 == '可视事件' then
            if 类型 == '鼠标移动' then
                if self:检查像素(x,y) then
                    if not self._已碰撞 then
                        self._已碰撞 = true
                        self:发送消息('获得鼠标焦点')
                    end
                    参数.碰撞 = true
                elseif self._已碰撞 then
                    self._已碰撞 = false
                    self:发送消息('失去鼠标焦点')
                end
            end
            if self._类型 == '窗口' then--窗口 相关
                if 类型 == '左键按下' then
                    if self:检查像素(x,y) then
                        self._鼠标按下 = true
                        self._cx,self._cy = x-self._x,y-self._y
                        self._层次 = os.clock() + 1000
                        self:取父控件():排序()--告诉父控件
                        return true
                    end
                elseif 类型 == '鼠标移动' then
                    if self._鼠标按下 then
                        self._x,self._y = x-self._cx,y-self._cy
                        self:_消息事件('坐标事件',{self._x,self._y})--告诉子控件
                        return true
                    end
                elseif 类型 == '左键弹起' or 类型 == '可视事件' then
                    self._鼠标按下 = false
                elseif 类型 == '右键按下' then
                    if self._父控件._右键关闭 and self:检查像素(x,y) then
                        self._鼠标按下 = false
                        self:置可视(false)
                        return true
                    end
                end
            end
            if self:发送消息('消息结束') then--拦截的呢消息
                return true
            elseif not self:是否禁止() and (类型 == '左键按下' or 类型 == '右键按下' or 类型 == '右键弹起' or 类型 == '鼠标滚动') then
                return self:检查像素(x,y)
            end
        end
    end
    return false
end

return GUI控件类